package main

import (
	"fmt"
	"time"
)

// 管道 协程
func main() {
	intChan := make(chan int, 1000)
	// 存放素数结果
	primeChan := make(chan int, 2000)
	// 标识退出结果
	exitChan := make(chan bool, 6)
	start := time.Now().UnixMilli()
	// 开一个协程 放入数据
	go func() {
		for i := 1; i < 80000; i++ {
			intChan <- i
		}
		// 关闭
		close(intChan)
	}()

	// 开启4个协程 取数据，判断是否为素数，如果是放入primeChan
	for i := 0; i < 6; i++ {
		go primeNum(intChan, primeChan, exitChan)
	}
	// 判断是否全部完成，再关闭主线程
	go func() {
		for i := 0; i < 6; i++ {
			<-exitChan
		}

		end := time.Now().UnixMilli()
		fmt.Println("耗时=", end-start)
		// 取出4个就说明都完成了
		close(primeChan)

	}()
	// 获取结果
	for {
		res, ok := <-primeChan
		if !ok {
			break
		}
		fmt.Printf("素数=%v\n", res)
	}
	fmt.Println("主线程结束")
}

func primeNum(intChan chan int, primeChan chan int, exitChan chan bool) {
	var flag bool
	for true {
		//time.Sleep(time.Millisecond)
		num, ok := <-intChan
		if !ok {
			// 取不到数据
			break
		}
		flag = true
		// 判断是否为素数
		for i := 2; i < num; i++ {
			if num%i == 0 {
				// 不是素数
				flag = false
				break
			}
		}
		if flag {
			primeChan <- num
		}
	}

	fmt.Println("有一个协程因为取不到数据退出")
	// 不能直接关闭primChan
	exitChan <- true
}
